﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using System.Windows;
using TLSC.common;
using TLSC.utils;

namespace TLSC
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainWindowViewModel windowViewModel;

        public SerialPort port;
        public int ReadTimeOut = 2000; // 连接超时
        public bool isSending = false;
        
        public MainWindow()
        {
            InitializeComponent();

            Log.SetTextControl(this.logger);

            this.Closing += new System.ComponentModel.CancelEventHandler(Windows_Closeing);
            this.btnOpenPort.Click += new RoutedEventHandler(OpenPort_Click);
            this.btnOpenFile.Click += new RoutedEventHandler(OpenFile_Click);
            this.btnSend.Click += new RoutedEventHandler(Send_Click);

            windowViewModel = new MainWindowViewModel();
            this.DataContext = windowViewModel;

            LoadCmbPortNo();
        }

        private void Windows_Closeing(object sender, CancelEventArgs e)
        {
            if(port != null)
            {
                port.Close();
                port.Dispose();
                port = null;
            }
            windowViewModel.Save();
        }

        private void Send_Click(object sender, RoutedEventArgs e)
        {
            if(port == null)
            {
                MessageBox.Show("串口未打开，请先打开串口在进行发送操作！！！", "系统提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (string.IsNullOrEmpty(windowViewModel.path))
            {
                MessageBox.Show("请先选择配置文件", "系统提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (isSending == true) return;

            isSending = true;

            ReadDate();
            myPort = new MySerialPort(port);

            Thread thread = new Thread(new ThreadStart(SendData));
            thread.Start();

        }

        
        private void delay(int millisecond)
        {
            DateTime sDt = DateTime.Now;
            DateTime dt = DateTime.Now;
            TimeSpan ts = dt - sDt;
            while (ts.TotalMilliseconds < millisecond)
            {
                dt = DateTime.Now;
                ts = dt - sDt;
            }
        }

        private void SendData()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                this.logger.Dispatcher.Invoke(() =>
                {
                    Log.Info("串口号：{0}", windowViewModel.selectPortNo);
                    Log.Info("波特率：{0}", windowViewModel.selectBaudRate);
                    Log.Info("共{0}组数据,发送中...", sendData.Count);
                });
            });

            if (sendData.Count > 0)
            {
                myPort.WirteNoReturn(sendData.Dequeue());
                //delay(12);
                delay(100);
            }

            int interval = windowViewModel.interval;
            while (true)
            {
                if (sendData.Count == 0)
                {
                    Log.Suc("发送成功");
                    isSending = false;
                    return;
                }

                myPort.WirteNoReturn(sendData.Dequeue());
                delay(interval);
                //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
            }
        }

        MySerialPort myPort;
        Queue<byte[]> sendData = new Queue<byte[]>();
        // v2.0.0
        private void ReadDate()
        {
            try
            {
                using (var reader = new StreamReader(File.OpenRead(windowViewModel.path)))
                {
                    ulong data = 0;
                    ushort add = 0;


                    int offset = 4;
                    while (!reader.EndOfStream)
                    {
                        byte[] bytes = new byte[20];
                        bytes[0] = 0xAA;
                        bytes[1] = 0xAA;
                        bytes[2] = 0x66;
                        bytes[3] = 0x66;
                        bytes[14] = 0x00;
                        bytes[15] = 0x00;
                        bytes[16] = 0x00;
                        bytes[17] = 0x00;
                        bytes[18] = 0x00;
                        bytes[19] = 0x00;

                        offset = 4;
                        var line = reader.ReadLine();

                        ulong.TryParse(line, out data);
                        DataConverter.UInt64ToBytes(bytes, offset, (UInt64)data);
                        offset += 8;
                        DataConverter.UInt16ToBytes(bytes, offset, (UInt16)add);
                        offset += 2;
                        sendData.Enqueue(bytes);
                        add += 8;
                        if(sendData.Count >= windowViewModel.sendCount)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error("数据读取失败");
                MessageBox.Show(ex.Message, "系统提示", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                isSending = false;
            }
        }

        // v1.0.0
        //private void ReadDate()
        //{
        //    try
        //    {
        //        using (var reader = new StreamReader(File.OpenRead(windowViewModel.path)))
        //        {
        //            int index = 0;
        //            int count = 0;
        //            ulong data = 0;
        //            ushort add = 0;


        //            int offset = 4;
        //            while (!reader.EndOfStream)
        //            {
        //                byte[] bytes = new byte[20];
        //                bytes[0] = 0xAA;
        //                bytes[1] = 0xAA;
        //                bytes[2] = 0x66;
        //                bytes[3] = 0x66;
        //                bytes[14] = 0x00;
        //                bytes[15] = 0x00;
        //                bytes[16] = 0x00;
        //                bytes[17] = 0x00;
        //                bytes[18] = 0x00;
        //                bytes[19] = 0x00;

        //                offset = 4;
        //                index++;
        //                var line = reader.ReadLine();
        //                if (index == 7)
        //                {
        //                    int.TryParse(line, out count);
        //                    DataConverter.UInt64ToBytes(bytes, offset, (UInt64)count);
        //                    offset += 8;
        //                    DataConverter.UInt16ToBytes(bytes, offset, (UInt16)add);
        //                    offset += 2;
        //                    sendData.Enqueue(bytes);
        //                    add += 8;
        //                }
        //                if (index > 8 && index <= (count + 8))
        //                {
        //                    ulong.TryParse(line, out data);
        //                    DataConverter.UInt64ToBytes(bytes, offset, (UInt64)data);
        //                    offset += 8;
        //                    DataConverter.UInt16ToBytes(bytes, offset, (UInt16)add);
        //                    offset += 2;
        //                    sendData.Enqueue(bytes);
        //                    add += 8;
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        Log.Error("数据读取失败");
        //        MessageBox.Show(ex.Message, "系统提示", MessageBoxButton.OK, MessageBoxImage.Error);
        //    }
        //    finally
        //    {
        //        isSending = false;
        //    }
        //}

        private void LoadCmbPortNo()
        {
            windowViewModel.portNos = MySerialPort.GetPortNames.ToList();
            if(windowViewModel.portNos.Count > 0)
            {
                windowViewModel.selectPortNo = windowViewModel.portNos[0];
            }
        }

        private void OpenPort_Click(object sender, RoutedEventArgs e)
        {
            int baudRate = 0;
            int.TryParse(windowViewModel.selectBaudRate, out baudRate);

            if(windowViewModel.portStatus == false)
            {
                try
                {
                    if(port == null)
                    {
                        port = new SerialPort(windowViewModel.selectPortNo,baudRate);
                    }
                    port.ReadTimeout = ReadTimeOut;
                    
                    port.Open();
                    windowViewModel.portStatus = true;
                    windowViewModel.btnName = "关闭串口";
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message
                        + "\r\n打开串口失败\r\n可能原因:\r\n串口正被其他程序使用\r\n解决方法：\r\n关闭其他程序后重试"
                        , "系统提示"
                        , MessageBoxButton.OK, MessageBoxImage.Error);
                    windowViewModel.portStatus = false;
                    windowViewModel.btnName = "打开串口";
                    port.Dispose();
                    port = null;
                }
            }
            else
            {
                if(port!= null)
                {
                    port.Close();
                    port = null;
                }
                windowViewModel.portStatus = false;
                windowViewModel.btnName = "打开串口";
            }
        }


        private void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "选择文件";
            openFileDialog.Filter = "csv文件|*.csv";
            if (!(bool)openFileDialog.ShowDialog())
            {
                return;
            }
            var filename = openFileDialog.FileName;
            windowViewModel.path = filename;

        }

        
    }

    public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {
            baudRateItems = new List<string>();
            baudRateItems.Add("110");
            baudRateItems.Add("300");
            baudRateItems.Add("600");
            baudRateItems.Add("1200");
            baudRateItems.Add("2400");
            baudRateItems.Add("4800");
            baudRateItems.Add("9600");
            baudRateItems.Add("14400");
            baudRateItems.Add("19200");
            baudRateItems.Add("38400");
            baudRateItems.Add("56000");
            baudRateItems.Add("57600");
            baudRateItems.Add("115200");
            baudRateItems.Add("128000");
            baudRateItems.Add("256000");
            selectBaudRate = "115200";

            portStatus = false;
            btnName = "打开串口";

            Load();
            //sendCount = 5008;
            //interval = 5;
        }

        public int Load()
        {
            try
            {
                using (var reader = new BinaryReader(File.OpenRead("conf")))
                { 
                    sendCount = reader.ReadInt32();
                    interval = reader.ReadInt32();
                }
            }catch{
                sendCount = 5008;
                interval = 5;
                return -1;
            }
            return 0;
        }

        public int Save()
        {
            try
            {
                using (var bw = new BinaryWriter(File.OpenWrite("conf")))
                {
                    bw.Write(sendCount);
                    bw.Write(interval);
                }
            }
            catch
            {
                return -1;
            }
            return 0;
        }

        private List<string> m_baudRateItems;
        public List<string> baudRateItems
        {
            get { return m_baudRateItems; }
            set
            {
                m_baudRateItems = value;
                NotifyPropertyChanged();
            }
        }

        private string m_selectBaudRate;
        public string selectBaudRate
        {
            get { return m_selectBaudRate;}
            set
            {
                m_selectBaudRate = value;
                NotifyPropertyChanged();
            }
        }

        private List<string> m_portNos;
        public List<string> portNos
        {
            get { return m_portNos; }
            set
            {
                m_portNos = value;
                NotifyPropertyChanged();
            }
        }

        private string m_selectPortNo;
        public string selectPortNo
        {
            get { return m_selectPortNo;}
            set
            {
                m_selectPortNo = value;
                NotifyPropertyChanged();
            }
        }

        private bool m_portStatus;
        public bool portStatus
        {
            get { return m_portStatus; }
            set
            {
                m_portStatus = value;
                NotifyPropertyChanged();
            }
        }

        private string m_btnName;
        public string btnName
        {
            get { return m_btnName; }
            set
            {
                m_btnName = value;
                NotifyPropertyChanged();
            }
        }

        private string m_path;
        public string path
        {
            get { return m_path; }
            set
            {
                m_path = value;
                NotifyPropertyChanged();
            }
        }

        private int m_sendCount;
        public int sendCount
        {
            get { return m_sendCount; }
            set
            {
                m_sendCount = value;
                NotifyPropertyChanged();
            }
        }

        private int m_interval;
        public int interval
        {
            get { return m_interval; }
            set
            {
                m_interval = value;
                NotifyPropertyChanged();
            }
        }
    }
}
